package com.google.code.p.localspinner.yahoo;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.text.MessageFormat;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import com.google.code.p.localspinner.AppUtils;
import com.google.code.p.localspinner.SearchException;
import com.google.code.p.localspinner.http.UserAgent;
import com.google.code.p.localspinner.model.Item;
import com.google.code.p.localspinner.model.ItemList;

public class UpcommingSearcher {

  private UserAgent userAgent = new UserAgent();
  private UserAgent userAgent2 = new UserAgent(true);
  private final XmlPullParser pullParser;
  private static final String GEOPLANET_BASE_QUERY = 
  "http://where.yahooapis.com/v1/places.q({0})?appid=GWWQB_jV34F9YKanNeXXCwqwTp83VqCaIIb11_3nAAhX2SypBXm7gCWZh4MpZKfdnw--";
  private static final String UPCOMMING_BASE_QUERY = 
    "http://upcoming.yahooapis.com/services/rest/?api_key=c71662e35a&method=event.getBestInPlace&woeid={0}";
  
  public UpcommingSearcher() throws SearchException{
    try {
      pullParser = XmlPullParserFactory.newInstance().newPullParser();
    } catch (XmlPullParserException e) {
      throw new SearchException("Unable to initialize xml parser", e);
    }
  }
  

  public ItemList searchPopularEvents(String location) throws SearchException{
    String woeid = searchWoeId(location);
    return search(woeid);
  }
  
  private ItemList search(String woeid) throws SearchException{
    String url = MessageFormat.format(UPCOMMING_BASE_QUERY, woeid);
    InputStream res = null;
    try {
      res = userAgent.getUrlAsStream(url);
      pullParser.setInput(new InputStreamReader(res));
      return parseResult(pullParser);
    } catch (Exception e) {
      throw new SearchException("Search failed", e);
    }finally{
      AppUtils.closeQuietly(res);
    }
  }
  
  private ItemList parseResult(XmlPullParser pullParser) throws XmlPullParserException, IOException{
    ItemList ret = new ItemList();
    int eventType = pullParser.getEventType();
    while(eventType != XmlPullParser.END_DOCUMENT){
      if(eventType == XmlPullParser.START_TAG){
          if("event".equalsIgnoreCase(pullParser.getName())){
            String title = pullParser.getAttributeValue(null, "name");
            StringBuilder body = new StringBuilder();
            String desc = pullParser.getAttributeValue(null, "description");
            if(desc != null){
              desc = desc.replaceAll("<[^>]*>", "");
              int end = Math.min(desc.length(), 70);
              body.append(desc.substring(0, end)+ (end == desc.length()? "\n" : "...\n"));
            }
            
            body.append(pullParser.getAttributeValue(null, "start_date")+" "+pullParser.getAttributeValue(null, "start_time"));
            String url = pullParser.getAttributeValue(null, "url");
            if(title != null){
              Item item = new Item(title, body.toString());
              item.setUrl(url);
              ret.addItem(item);
            }
          }
      }
      eventType = pullParser.next();
    }
    return ret;
  }
  
  private String searchWoeId(String location) throws SearchException{
    String url = MessageFormat.format(GEOPLANET_BASE_QUERY, URLEncoder.encode("'"+location+"'"));
    InputStream res = null;
    try {
      res = userAgent2.getUrlAsStream(url);
      pullParser.setInput(new InputStreamReader(res));
      return parseGeoResult(pullParser);
    } catch (Exception e) {
      throw new SearchException("Search failed", e);
    }finally{
      AppUtils.closeQuietly(res);
    }
  }
  
  private String parseGeoResult(XmlPullParser pullParser) throws XmlPullParserException, IOException{
    int eventType = pullParser.getEventType();
    while(eventType != XmlPullParser.END_DOCUMENT){
      if(eventType == XmlPullParser.START_TAG
          && "woeid".equalsIgnoreCase(pullParser.getName())){
            eventType = pullParser.next();
            if(eventType == XmlPullParser.TEXT){
              return pullParser.getText();
            }
      }
      eventType = pullParser.next();
    }
    return null;
  }

}
